package com.yanqu.road.server.channelserver.manager.activity.entername;

import com.yanqu.road.entity.log.LogEnterNameActivityRank;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.cross3.activity.XRankProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameGroupRank;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameGroupRankModel;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRank;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRankModel;
import com.yanqu.road.server.channelserver.manager.log.impl.ChannelLogEnterNameLogic;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelEnterNameRankMgr extends TempMgr {

    //activityId  type  matchGroupKey
    static Map<Integer, Map<Integer, Map<Integer, EnterNameRankModel>>> userRankMap = new ConcurrentHashMap<>();

    //activityId  type  matchGroupKey
    static Map<Integer, Map<Integer, Map<Integer, EnterNameGroupRankModel>>> groupValueMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        //初始榜单
        //业务数据及报名数据加载后 进行初始化
        for (Map.Entry<Integer, EnterNameActivity> activityEntry : ChannelEnterNameMgr.getNameActivityMap().entrySet()) {
            activityEntry.getValue().initDataRank();
        }
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    public static void changeUserRank(int activityId, int type, int matchGroupId, EnterNameRank rank){
        Map<Integer, Map<Integer, EnterNameRankModel>> typeMap = userRankMap.get(activityId);
        if(typeMap == null){
            synchronized (userRankMap){
                typeMap = userRankMap.get(activityId);
                if(typeMap == null){
                    typeMap = new ConcurrentHashMap<>();
                    userRankMap.put(activityId, typeMap);
                }
            }
        }
        Map<Integer, EnterNameRankModel> map = typeMap.get(type);
        if(map == null){
            synchronized (typeMap){
                map = typeMap.get(type);
                if(map == null){
                    map = new ConcurrentHashMap<>();
                    typeMap.put(type, map);
                }
            }
        }
        EnterNameRankModel model = map.get(matchGroupId);
        if(model == null){
            synchronized (map){
                model = map.get(matchGroupId);
                if(model == null){
                    model = new EnterNameRankModel(activityId, type, matchGroupId);
                    model.setRankList(new LinkedList<>());
                    map.put(matchGroupId, model);
                }
            }
        }
        if(rank != null){
            model.rankChange(rank);
            //getLogger().info("enter name change user {}, value {}", rank.getUserId(), rank.getValue().toString());
            changeZoneTop50UserRank(activityId, type, rank.getZoneId(), rank);
        }

    }

    public static void changeGroupValue(int activityId, int type, int matchGroupId, EnterNameGroupRank rank){
        Map<Integer, Map<Integer, EnterNameGroupRankModel>> typeMap = groupValueMap.get(activityId);
        if(typeMap == null){
            synchronized (groupValueMap){
                typeMap = groupValueMap.get(activityId);
                if(typeMap == null){
                    typeMap = new ConcurrentHashMap<>();
                    groupValueMap.put(activityId, typeMap);
                }
            }
        }
        Map<Integer, EnterNameGroupRankModel> map = typeMap.get(type);
        if(map == null){
            synchronized (typeMap){
                map = typeMap.get(type);
                if(map == null){
                    map = new ConcurrentHashMap<>();
                    typeMap.put(type, map);
                }
            }
        }
        EnterNameGroupRankModel model = map.get(matchGroupId);
        if(model == null){
            synchronized (map){
                model = map.get(matchGroupId);
                if(model == null){
                    model = new EnterNameGroupRankModel(activityId, type, matchGroupId);
                    model.setRankList(initGroupRank(activityId, matchGroupId, type));
                    map.put(matchGroupId, model);
                }
            }
        }
        if(rank != null){
            model.rankChange(rank);
            //getLogger().info("enter name change type {} matchGroup {}, value {}", rank.getType(), rank.getGroupId(), rank.getValue().toString());
        }
    }

    public static EnterNameGroupRankModel getEnterNameGroupRankModel(int activityId, int type, int matchGroupId){
        Map<Integer, Map<Integer, EnterNameGroupRankModel>> matchGroupMap = groupValueMap.get(activityId);
        if(matchGroupMap == null){
            return null;
        }
        Map<Integer, EnterNameGroupRankModel> typeMap = matchGroupMap.get(type);
        if(typeMap == null){
            return null;
        }
        return typeMap.get(matchGroupId);
    }

    public static EnterNameRankModel getEnterNameRankModel(int activityId, int type, int matchGroupId){
        Map<Integer, Map<Integer, EnterNameRankModel>> matchGroupMap = userRankMap.get(activityId);
        if(matchGroupMap == null){
            return null;
        }
        Map<Integer, EnterNameRankModel> typeMap = matchGroupMap.get(type);
        if(typeMap == null){
            return null;
        }
        return typeMap.get(matchGroupId);
    }


    public static Map<Integer, Map<Integer, Map<Integer, EnterNameRankModel>>> getUserRankMap() {
        return userRankMap;
    }

    //特殊，缓存各地区top50的排行
    public static void changeZoneTop50UserRank(int activityId, int type, int zoneId, EnterNameRank rank){
        if(zoneId > 0){
            Map<Integer, Map<Integer, EnterNameRankModel>> typeMap = userRankMap.get(activityId);
            if(typeMap == null){
                synchronized (userRankMap){
                    typeMap = userRankMap.get(activityId);
                    if(typeMap == null){
                        typeMap = new ConcurrentHashMap<>();
                        userRankMap.put(activityId, typeMap);
                    }
                }
            }
            Map<Integer, EnterNameRankModel> map = typeMap.get(type);
            if(map == null){
                synchronized (typeMap){
                    map = typeMap.get(type);
                    if(map == null){
                        map = new ConcurrentHashMap<>();
                        typeMap.put(type, map);
                    }
                }
            }
            EnterNameRankModel model = map.get(zoneId);
            if(model == null){
                synchronized (map){
                    model = map.get(zoneId);
                    if(model == null){
                        model = new EnterNameRankModel(activityId, type, zoneId, 50);
                        model.setRankList(new LinkedList<>());
                        map.put(zoneId, model);
                    }
                }
            }
            if(rank != null){
                model.rankChange(rank);
            }
        }
    }

    public static XRankProto.XUserRankMsg.Builder buildRankMsg(EnterNameRank rank){
        XRankProto.XUserRankMsg.Builder builder = XRankProto.XUserRankMsg.newBuilder();
        builder.setUserId(rank.getUserId());
        builder.setChannelId(rank.getChannelId());
        builder.setValue(rank.getValue().toString());
        builder.setParam(rank.getParam());
        builder.setExtendParam(String.valueOf(rank.getZoneId()));
        builder.setUpdateTime(rank.getLastUpdateTime());
        builder.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(rank.getUserBaseInfo()));
        return builder;
    }

    public static void initRank(int activityId, int type, Map<Integer, EnterNameRankModel> matchRankModelMap) {
        Map<Integer, Map<Integer, EnterNameRankModel>> typeMap = userRankMap.get(activityId);
        if(typeMap == null){
            synchronized (userRankMap){
                typeMap = userRankMap.get(activityId);
                if(typeMap == null){
                    typeMap = new ConcurrentHashMap<>();
                    userRankMap.put(activityId, typeMap);
                }
            }
        }
        synchronized (typeMap){
            if(!typeMap.containsKey(type)){
                typeMap.put(type, new ConcurrentHashMap<>());
            }
            typeMap.get(type).putAll(matchRankModelMap);
        }
    }

    public static void initGroupRank(int activityId, int type, Map<Integer, EnterNameGroupRankModel> matchRankModelMap) {
        Map<Integer, Map<Integer, EnterNameGroupRankModel>> typeMap = groupValueMap.get(activityId);
        if(typeMap == null){
            synchronized (groupValueMap){
                typeMap = groupValueMap.get(activityId);
                if(typeMap == null){
                    typeMap = new ConcurrentHashMap<>();
                    groupValueMap.put(activityId, typeMap);
                }
            }
        }
        synchronized (typeMap){
            if(!typeMap.containsKey(type)){
                typeMap.put(type, new ConcurrentHashMap<>());
            }
            typeMap.get(type).putAll(matchRankModelMap);
        }
    }

    public static LinkedList initGroupRank(int activityId, int matchGroupId, int type){
        EnterNameModel model = ChannelEnterNameMgr.getEnterNameModel(activityId);
        if(model != null){
            return model.initGroupRank(matchGroupId, type);
        }
        return new LinkedList();
    }

    public static EnterNameRank getEnterNameRank(long userId, int channelId, int groupId, int conditionType, long lastUpdateTime, BigInteger value, String param, UserBaseInfo userBaseInfo) {
        EnterNameRank rank = new EnterNameRank();
        rank.setUserId(userId);
        rank.setChannelId(channelId);
        rank.setGroupId(groupId);
        rank.setConditionType(conditionType);
        rank.setLastUpdateTime(lastUpdateTime);
        rank.setValue(value);
        rank.setParam(param);
        rank.setUserBaseInfo(userBaseInfo);
        return rank;
    }

    public static Map<Integer, Map<Integer, Map<Integer, EnterNameGroupRankModel>>> getGroupValueMap() {
        return groupValueMap;
    }

    public static void saveEnterNameRank(){
        try{
            for (Map.Entry<Integer, Map<Integer, Map<Integer, EnterNameRankModel>>> entry : ChannelEnterNameRankMgr.getUserRankMap().entrySet()) {
                EnterNameModel enterNameModel = ChannelEnterNameMgr.getEnterNameModel(entry.getKey());
                if(enterNameModel == null){
                    continue;
                }
                if(!ChannelEnterNameMgr.activityInSaveRankPeriod(enterNameModel.getActivityInfo())){
                    continue;
                }
                for (Map.Entry<Integer, Map<Integer, EnterNameRankModel>> mapEntry : entry.getValue().entrySet()) {
                    for (Map.Entry<Integer, EnterNameRankModel> modelEntry : mapEntry.getValue().entrySet()) {
                        EnterNameRankModel model = modelEntry.getValue();
                        if(model.isSave()){
                            continue;
                        }
                        model.setSave(true);
                        Date now = new Date();
                        LinkedList<EnterNameRank> rankList = model.getRankList();
                        List<LogEnterNameActivityRank> logList = new ArrayList<>();
                        for (int i = 0; i < rankList.size(); i++) {
                            EnterNameRank enterNameRank = rankList.get(i);
                            LogEnterNameActivityRank log = new LogEnterNameActivityRank(enterNameModel.getActivityInfo().getActivityId(),
                                    model.getConditionType(),
                                    model.getMatchGroupId(),
                                    i + 1,
                                    enterNameRank.getUserId(),
                                    enterNameRank.getZoneId(),
                                    enterNameRank.getLastUpdateTime(),
                                    now);
                            logList.add(log);
                        }
                        ChannelLogEnterNameLogic.addLogEnterNameRankList(logList);
                    }
                }
            }
        }catch (Exception e){
            getLogger().error(e.getMessage(), e);
        }
    }

    public static void saveEnterNameGroupRank(){
        try{
            for (Map.Entry<Integer, Map<Integer, Map<Integer, EnterNameGroupRankModel>>> entry : ChannelEnterNameRankMgr.getGroupValueMap().entrySet()) {
                EnterNameModel enterNameModel = ChannelEnterNameMgr.getEnterNameModel(entry.getKey());
                if(enterNameModel == null){
                    continue;
                }
                if(!ChannelEnterNameMgr.activityInSaveRankPeriod(enterNameModel.getActivityInfo())){
                    continue;
                }
                for (Map.Entry<Integer, Map<Integer, EnterNameGroupRankModel>> mapEntry : entry.getValue().entrySet()) {
                    for (Map.Entry<Integer, EnterNameGroupRankModel> modelEntry : mapEntry.getValue().entrySet()) {
                        EnterNameGroupRankModel model = modelEntry.getValue();
                        if(model.isSave()){
                            continue;
                        }
                        model.setSave(true);
                        Date now = new Date();
                        LinkedList<EnterNameGroupRank> rankList = model.getRankList();
                        List<LogEnterNameActivityRank> logList = new ArrayList<>();
                        for (int i = 0; i < rankList.size(); i++) {
                            EnterNameGroupRank groupRank = rankList.get(i);
                            LogEnterNameActivityRank log = new LogEnterNameActivityRank(enterNameModel.getActivityInfo().getActivityId(),
                                    model.getConditionType(),
                                    model.getMatchGroupId(),
                                    i + 1,
                                    groupRank.getGroupId(),
                                    0,
                                    groupRank.getLastUpdateTime(),
                                    now);
                            logList.add(log);
                        }
                        ChannelLogEnterNameLogic.addLogEnterNameRankList(logList);
                    }
                }
            }
        }catch (Exception e){
            getLogger().error(e.getMessage(), e);
        }
    }
}
